package com.bawan.vims.common.security;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.List;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;

/**
 * RSA加密
 * <p> Description	: RSAHelper.java </p>
 * <p> Copyright	: Copyright (c) 2015 by FITT</p>
 * <p> Author 		: ZCC </p>
 * <p> Create		: 2015年3月11日 上午9:57:00 </p> 
 * <p> version 		: 1.0 </p>
 */
public abstract class RSAHelper {
	private static Cipher cipher1;
	private static Cipher cipher2;
	private static Cipher cipher3;
	private static Cipher cipher4;

	static {
		init();
	}

	private static void init() {

		try {
			KeyFactory keyFactory = getRSAKeyFactory();
			initPulbicKeyCipher(keyFactory);
			initPrivateKeyCipher(keyFactory);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("rawtypes")
	private static void initPrivateKeyCipher(KeyFactory keyFactory)
			throws IOException, InvalidKeySpecException,
			NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidKeyException {
		InputStream input = RSAHelper.class.getResourceAsStream("private.txt");
		StringBuilder pri = new StringBuilder(128);
		List list2 = IOUtils.readLines(input);
		IOUtils.closeQuietly(input);
		for (int i = 0; i < list2.size(); ++i) {
			pri.append((String) list2.get(i));
		}
		byte[] privateKeyBytes = Base64Util.decrypt(pri.toString());
		PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
				privateKeyBytes);
		PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8);
		cipher2 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher2.init(Cipher.DECRYPT_MODE, privateKey);
		cipher4 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher4.init(Cipher.ENCRYPT_MODE, privateKey);
	}

	@SuppressWarnings("rawtypes")
	private static void initPulbicKeyCipher(KeyFactory keyFactory)
			throws IOException, InvalidKeySpecException,
			NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidKeyException {
		InputStream input = RSAHelper.class
				.getResourceAsStream("public.txt");
		StringBuilder pub = new StringBuilder(128);
		List list1 = IOUtils.readLines(input);
		IOUtils.closeQuietly(input);
		for (int i = 0; i < list1.size(); ++i) {
			pub.append((String) list1.get(i));
		}
		byte[] publicKeyBytes = Base64Util.decrypt(pub.toString());
		
		X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(
				publicKeyBytes);
		PublicKey publicKey = keyFactory.generatePublic(bobPubKeySpec);
		cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher1.init(Cipher.ENCRYPT_MODE, publicKey);
		cipher3 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher3.init(Cipher.DECRYPT_MODE, publicKey);
	}

	private static KeyFactory getRSAKeyFactory()
			throws NoSuchAlgorithmException {
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		return keyFactory;
	}

	public static byte[] encryptWithPublicKey(byte[] data) {
		try {
			return cipher1.doFinal(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static byte[] encryptWithPrivateKey(byte[] data) {
		try {
			return cipher4.doFinal(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static byte[] decryptWithPrivateKey(byte[] data) {
		try {
			//return cipher2.doFinal(data);
			//分段解密，不然大于128报错
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < data.length; i += 128) { 
				byte[] doFinal = cipher2.doFinal(ArrayUtils.subarray(data, i, i + 128));
			    sb.append(new String(doFinal));
			 }
			return sb.toString().getBytes();

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static byte[] decryptWithPublicKey(byte[] data) {
		try {
			return cipher3.doFinal(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws Exception {
		/*
		 * KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
		 * keyPairGen.initialize(1024); KeyPair keyPair =
		 * keyPairGen.generateKeyPair(); System.out.println("public:" +
		 * keyPair.getPublic().getEncoded().length);
		 * System.out.println("public:" +
		 * Base64Util.encrypt(keyPair.getPublic().getEncoded()));
		 * System.out.println("*********************************************");
		 * System.out.println("privte:" +
		 * Base64Util.encrypt(keyPair.getPrivate().getEncoded()));
		 */
		
		String str = "123456";
		String base64Str = Base64Util.encrypt(RSAHelper.encryptWithPrivateKey(str.getBytes()));
		System.out.println(base64Str);
		byte[] bytes = Base64Util.decrypt(base64Str);
		String result = new String(RSAHelper.decryptWithPublicKey(bytes));
		System.out.println(result);
		
		/*
		String s = "GMQTHepH8JiVv8Zpgbmet6waFivXXOpuWoMhK46z7dTAMEqGP22eWUkij0ZWlJpt3bktqUNDGkj+\r\nmyNks/taeXMOXC3spMlpfEjUOqNvHkx0jduEgSWijstQW8lL58O7AZxWWAxcD3zDBfKrP1inEREF\r\n2Jpl99R3jqivpTEqvoI=";
		System.out.println(s.length());
		String ss = new String(RSAHelper.decryptWithPublicKey(Base64Util.decrypt(s)));
		System.out.println(ss);
		*/
	}
}
